package com.dataView.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 日期操作辅助类
 * 
 * @version $Id: DateUtil.java, v 0.1 2014年3月28日 上午8:58:11 ShenHuaJie Exp $
 */
public final class DateUtil {
	private DateUtil() {
	}
	/** 日期格式 **/
    public interface DATE_PATTERN {
        String HHMMSS = "HHmmss";
        String HH_MM_SS = "HH:mm:ss";
        String YYYYMMDD = "yyyyMMdd";
		String YYYYMM = "yyyyMM";
        String YYYY_MM_DD = "yyyy-MM-dd";
        String YYYY_MM_DD_SEP = "yyyy/MM/dd";
        String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
        String YYYYMMDDHHMM = "yyyyMMddHHmm";
        String YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";
        String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
        String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
        String D_H_M_S = "%d天%d小时%d分钟%d秒";
        String YYYYMMDD_IN_CHAINA = "yyyy年MM月dd日";
    }

	/**
	 * 格式化日期
	 * 
	 * @param date
	 * @param pattern
	 * @return
	 */
	public static final String format(Object date) {
		return format(date, DATE_PATTERN.YYYY_MM_DD);
	}

	/**
	 * 格式化日期
	 * 
	 * @param date
	 * @param pattern
	 * @return
	 */
	public static final String format(Object date, String pattern) {
		if (date == null) {
			return null;
		}
		if (pattern == null) {
			return format(date);
		}
		return new SimpleDateFormat(pattern).format(date);
	}

	/**
	 * 获取日期
	 * 
	 * @return
	 */
	public static final String getDate() {
		return format(new Date());
	}
	
	public static final String getYearMonth() {
		return format(new Date(), DATE_PATTERN.YYYYMM);
	}

	/**
	 * 获取日期时间
	 * 
	 * @return
	 */
	public static final String getDateTime() {
		return format(new Date(), DATE_PATTERN.YYYY_MM_DD_HH_MM_SS);
	}

	/**
	 * 获取日期
	 * 
	 * @param pattern
	 * @return
	 */
	public static final String getDateTime(String pattern) {
		return format(new Date(), pattern);
	}

	/**
	 * 日期计算
	 * 
	 * @param date
	 * @param field
	 * @param amount
	 * @return
	 */
	public static final Date addDate(Date date, int field, int amount) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(field, amount);
		return calendar.getTime();
	}

	/**
	 * 字符串转换为日期:不支持yyM[M]d[d]格式
	 * 
	 * @param date
	 * @return
	 */
	public static final Date stringToDate(String date) {
		if (date == null) {
			return null;
		}
		String separator = String.valueOf(date.charAt(4));
		String pattern = "yyyyMMdd";
		if (!separator.matches("\\d*")) {
			pattern = "yyyy" + separator + "MM" + separator + "dd";
			if (date.length() < 10) {
				pattern = "yyyy" + separator + "M" + separator + "d";
			}
		} else if (date.length() < 8) {
			pattern = "yyyyMd";
		}
		pattern += " HH:mm:ss.SSS";
		pattern = pattern.substring(0, Math.min(pattern.length(), date.length()));
		try {
			return new SimpleDateFormat(pattern).parse(date);
		} catch (ParseException e) {
			return null;
		}
	}
	
	/**
	 * 字符串转换为日期:不支持yyM[M]d[d]格式
	 * 
	 * @param date
	 * @return
	 */
	public static final Date stringToDate(String date, String pattern) {
		if (date == null) {
			return null;
		}
		try {
			return new SimpleDateFormat(pattern).parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 间隔天数
	 * 
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static final Integer getDayBetween(Date startDate, Date endDate) {
		Calendar start = Calendar.getInstance();
		start.setTime(startDate);
		start.set(Calendar.HOUR_OF_DAY, 0);
		start.set(Calendar.MINUTE, 0);
		start.set(Calendar.SECOND, 0);
		start.set(Calendar.MILLISECOND, 0);
		Calendar end = Calendar.getInstance();
		end.setTime(endDate);
		end.set(Calendar.HOUR_OF_DAY, 0);
		end.set(Calendar.MINUTE, 0);
		end.set(Calendar.SECOND, 0);
		end.set(Calendar.MILLISECOND, 0);

		long n = end.getTimeInMillis() - start.getTimeInMillis();
		return (int) (n / (60 * 60 * 24 * 1000l));
	}

	/**
	 * 间隔月
	 * 
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static final Integer getMonthBetween(Date startDate, Date endDate) {
		if (startDate == null || endDate == null || !startDate.before(endDate)) {
			return null;
		}
		Calendar start = Calendar.getInstance();
		start.setTime(startDate);
		Calendar end = Calendar.getInstance();
		end.setTime(endDate);
		int year1 = start.get(Calendar.YEAR);
		int year2 = end.get(Calendar.YEAR);
		int month1 = start.get(Calendar.MONTH);
		int month2 = end.get(Calendar.MONTH);
		int n = (year2 - year1) * 12;
		n = n + month2 - month1;
		return n;
	}

	/**
	 * 间隔月，多一天就多算一个月
	 * 
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static final Integer getMonthBetweenWithDay(Date startDate, Date endDate) {
		if (startDate == null || endDate == null || !startDate.before(endDate)) {
			return null;
		}
		Calendar start = Calendar.getInstance();
		start.setTime(startDate);
		Calendar end = Calendar.getInstance();
		end.setTime(endDate);
		int year1 = start.get(Calendar.YEAR);
		int year2 = end.get(Calendar.YEAR);
		int month1 = start.get(Calendar.MONTH);
		int month2 = end.get(Calendar.MONTH);
		int n = (year2 - year1) * 12;
		n = n + month2 - month1;
		int day1 = start.get(Calendar.DAY_OF_MONTH);
		int day2 = end.get(Calendar.DAY_OF_MONTH);
		if (day1 <= day2) {
			n++;
		}
		return n;
	}
	
	  /**
     * 获取两个日期之间的日期
     * 
     * @param start
     *            开始日期
     * @param end
     *            结束日期
     * @return 日期集合
     */
    public static List<String> getBetweenDates(String start, int between) {
        return getBetweenDates(start, between, "yyyyMMdd");
    }

    /**
     * 获取两个日期之间的日期
     * 
     * @param start
     *            开始日期
     * @param between
     *            间隔天数（正数：开始日期往后算，负数：开始日期往前算）
     * @param dateFormat
     *            日期格式
     * @return 日期集合
     */
    public static List<String> getBetweenDates(String start, int between, String dateFormat) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        List<String> result = new ArrayList<String>();
        Calendar tempStart = Calendar.getInstance();
        try {
            tempStart.setTime(sdf.parse(start));
        } catch (ParseException e) {
        }
        result.add(start);
        int betweebAbs = Math.abs(between);
        while (betweebAbs > 0) {
            if (between > 0) {
            	 tempStart.add(Calendar.DAY_OF_YEAR, 1);
            } else {
            	tempStart.add(Calendar.DAY_OF_YEAR, -1);
            }
            result.add(sdf.format(tempStart.getTime()));
            betweebAbs --;
        }
        return result;
    }

	/**
	 * 返回明天（
	 * @return
	 */
    public static Date getTomorrowDay() {
  	  Calendar now = Calendar.getInstance();
  	  now.setTimeInMillis(System.currentTimeMillis());
  	  now.add(Calendar.DAY_OF_YEAR, 1);
  	  return now.getTime();
  }

    
    /**
     * 返回昨天（yyyy-MM-dd）
     * @return
     */
    public static String getYesterdayStr() {
  	  Calendar now = Calendar.getInstance();
  	  now.setTimeInMillis(System.currentTimeMillis());
  	  now.add(Calendar.DAY_OF_YEAR, -1);
  	  return format(now.getTime());
    }
    
    public static String getTomorowStr() {
    	  Calendar now = Calendar.getInstance();
    	  now.setTimeInMillis(System.currentTimeMillis());
    	  now.add(Calendar.DAY_OF_YEAR, 1);
    	  return format(now.getTime(),"yyyyMMdd");
      }
    
    /**
     * 返回昨天（给定format）
     * @return
     */
    public static String getYesterdayStr(String format) {
  	  Calendar now = Calendar.getInstance();
  	  now.setTimeInMillis(System.currentTimeMillis());
  	  now.add(Calendar.DAY_OF_YEAR, -1);
  	  return format(now.getTime(), format);
    }
    
    /**
     * 计算两个时间之间差额并format。(dd天HH小时mm分钟ss秒)
     * 
     * @return
     */
    public static String getBetweenTime(Date start, Date end) {
    	if (start == null || end == null) {
    		return null;
    	}
    	long startMills = start.getTime();
    	long endMills = end.getTime();
    	long count = endMills - startMills;
    	long dayMills = 24 * 60 * 60 * 1000;
    	long hourMills = 60 * 60 * 1000;
    	long minuteMills = 60 * 1000;
    	long secondMills = 1000;
    	
    	long day = (count) / dayMills;
    	long hour = (count - day * dayMills) / hourMills;
    	long minute = (count - day * dayMills - hour * hourMills) / minuteMills;
    	long second = (count - day * dayMills - hour * hourMills - minute * minuteMills)/ secondMills;
    	
    	return String.format(DATE_PATTERN.D_H_M_S, new Object[]{day, hour, minute, second});
    }
    
    /**
     * 返回当前时间是周几（1、2...）
     */
    public static int getDayOfWeek() {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTimeInMillis(System.currentTimeMillis());
    	return calendar.get(Calendar.DAY_OF_WEEK) - 1;
    }
    
    /**
     * 返回当前时间是周几（1、2...）
     */
    public static int getDayOfWeek(Date date) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
    	return calendar.get(Calendar.DAY_OF_WEEK) - 1;
    }
    
    /**
     * 判断time是否在from，to之内
     * @author victor
     * @since 2018-04-18
     * @param time 指定日期
     * @param from 开始日期
     * @param to   结束日期
     * @return
     */
    public static boolean isInDateRange(Date time, Date from, Date to) {
        Calendar date = Calendar.getInstance();
        date.setTime(time);

        Calendar after = Calendar.getInstance();
        after.setTime(from);

        Calendar before = Calendar.getInstance();
        before.setTime(to);

        if (date.after(after) && date.before(before)) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * 判断当前日期是否等于from或者to
     * @author victor
     * @since 2018-04-18
     * @param from 开始日期
     * @param to   结束日期
     */
    public static boolean isEqualsDateRange(String from, String to) {
    	String nowDate=getDate();
        if (nowDate.equals(from)||nowDate.equals(to)) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * 判断当前时间是否为指定时间
     * @author victor
     * @since 2018-04-18
     * @param timeStr 指定时间
     * @param timePattern  时间格式,如HH:mm或者HH:mm:ss
     */
    public static boolean isEqualsTime(String timeStr,String timePattern){
    	Date d = new Date();
    	SimpleDateFormat sdf = new SimpleDateFormat(timePattern);
    	String result=sdf.format(d);
    	if(result.equals(timeStr)){
    		 return true;
    	}else{
    		 return false;
    	}
    }

	/**
	 * 返回当前小时 24-hour clock.
	 * @return
	 */
	public static int getCurrentHour() {
		Calendar now = Calendar.getInstance();
		return now.get(Calendar.HOUR_OF_DAY);
	}

	/**
	 * 获取当前月份
	 * @return
	 */
	public static int getCurrentMonth() {
		Calendar now = Calendar.getInstance();
		return now.get(Calendar.MONTH) + 1;
	}
	
	/**
     * 指定日期和日期间隔，返回间隔之前的日期
     * @param specifiedDay
     * @param interval
     * @return
     */
    public static String getSpecifiedDayAgo(String specifiedDay, int interval){
        return getSpecifiedDay(specifiedDay, interval, "-");
    }

    /**
     * 指定日期和日期间隔，返回间隔之前的日期
     * @param specifiedDay
     * @param interval
     * @return
     */
    public static String getSpecifiedDayAfter(String specifiedDay, int interval){
        return getSpecifiedDay(specifiedDay, interval, "+");
    }

    private static String getSpecifiedDay(String specifiedDay, int interval, String func) {
        Calendar c = Calendar.getInstance();
        Date date = null;
        try {
            date = new SimpleDateFormat("yyyy-MM-dd").parse(specifiedDay);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        c.setTime(date);
        int day=c.get(Calendar.DATE);

        if("+".equals(func)) {
            c.set(Calendar.DATE, day + interval);
        } else if("-".equals(func)) {
            c.set(Calendar.DATE, day - interval);
        } else {
            return null;
        }

        String dayAfter = new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
        return dayAfter;
    }
    
    /**
     * 获取当前日期,输出格式为yyyy-MM-dd
     * @author victor
     * @since 2018-05-21
     * @return 当前日期
     */
    public static String getToday(){
        Date d = new Date();  
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");  
        String dateNowStr = sdf.format(d);  
        return dateNowStr;
    }
    
    /**
     * 获取当前日期,输出格式为yyyy-MM-dd HH:mm
     * @author victor
     * @since 2018-05-21
     * @return 当前日期
     */
    public static String getTodayMinute(){
        Date d = new Date();  
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");  
        String dateNowStr = sdf.format(d);  
        return dateNowStr;
    }
    
    /**
     * 比较两个日期的大小。date1<date2,返回-1;date1=date2,返回0;date1>date2,返回1
     * @author victor
     * @since 2018-05-21
     * @param date1 第一个日期
     * @param date2 第二个日期
     * @return 日期差值
     */
    public static int compareDate(String date1, String date2) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        int result=0;
        try {
            Date dt1 =df.parse(date1);
            Date dt2 =df.parse(date2);
            if (dt1.getTime() > dt2.getTime()) {
               result=1;
            } else if(dt1.getTime() < dt2.getTime()) {
               result=-1;
            }else{
               result=0;
            }

        } catch (Exception exception) {
           exception.printStackTrace();
        }
        return result;
      }
    
    /**
     * 查询指定日期跨度内的所有日期
     * @param dBegin 起始日期
     * @param dEnd 结束日期
     * @return
     */
    public static List<Date> findDates(Date dBegin, Date dEnd){  
	     List<Date> lDate = new ArrayList<Date>();  
	     lDate.add(dBegin);  
	     Calendar calBegin = Calendar.getInstance();  
	     // 使用给定的 Date 设置此 Calendar 的时间  
	     calBegin.setTime(dBegin);  
	     Calendar calEnd = Calendar.getInstance();  
	     // 使用给定的 Date 设置此 Calendar 的时间  
	     calEnd.setTime(dEnd);  
	     // 测试此日期是否在指定日期之后  
	     while (dEnd.after(calBegin.getTime())){  
	    	 // 根据日历的规则，为给定的日历字段添加或减去指定的时间量  
		      calBegin.add(Calendar.DAY_OF_MONTH, 1);  
		      lDate.add(calBegin.getTime());  
	     }  
	     return lDate;  
    }  
    
    
    /**
     * 当前日期加上天数后的日期
     * @param num 为增加的天数,可以为负数,为负数时则是前num天的日期
     * @return yyyy-MM-dd格式的日期
     * @author Victor
     * @since 2018-08-07
     */
    public static String plusDay(int num){
        Date d = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String currdate = format.format(d);
        System.out.println("现在的日期是：" + currdate);
        Calendar ca = Calendar.getInstance();
        ca.add(Calendar.DATE, num);// num为增加的天数，可以改变的
        d = ca.getTime();
        String enddate = format.format(d);
        System.out.println("增加天数以后的日期：" + enddate);
        return enddate;
    }
    
    /**
     * 根据开始和结束时间返回包含星期的日期
     * @param start
     * @param end
     * @param weeks
     * @return
     */
    public static List<Date> getBetweenDateByWeek(Date start,  Date end, List<String> weeks) {
        // 星期
        final String[] weekDays = {"7", "1", "2", "3", "4", "5", "6"};
        List<Date> results = new ArrayList<>();
        List<Date> dates = getBetweenDate(start, end);
        for(Date c : dates) {
            Calendar current = Calendar.getInstance();
            current.setTime(c);
            int dayOfWeek = current.get(Calendar.DAY_OF_WEEK)-1;
            String dow = weekDays[dayOfWeek]; // 获取星期
            if(weeks.contains(dow)) {
                results.add(c);
            }
        }
        return results;
    }

    /**
     * 计算开始日期
     * @param start 开始日期
     * @param end 结束日期
     * @return 返回开始和结束日期之间的日期
     */
    public static List<Date> getBetweenDate(Date start,  Date end) {
        if(start == null || end == null || start.compareTo(end) == 1) {
            return new ArrayList<>();
        }
        List<Date> results = new ArrayList<>();
        Calendar startDay = Calendar.getInstance();
        Calendar endDay = Calendar.getInstance();
        startDay.setTime(start);
        endDay.setTime(end);
        while(startDay.compareTo(endDay) != 0) {
            results.add(startDay.getTime());
            startDay.add(Calendar.DATE, 1);
        }
        results.add(endDay.getTime());
        return results;
    }
    
    /**
     * 获取两个日期字符串之间的日期集合
     * @param startTime:String
     * @param endTime:String
     * @return list:yyyy-MM-dd
     */
    public static List<String> getBetweenDate(String startTime, String endTime){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 声明保存日期集合
        List<String> list = new ArrayList<String>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);
 
            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime()<=(endDate.getTime())){
                // 把日期添加到集合
                list.add(sdf.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把日期增加一天
                calendar.add(Calendar.DATE, 1);
                // 获取增加后的日期
                startDate=calendar.getTime();
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

	/**
	 * 获取明天0点的时间
	 * @return 获取今天0点的时间
	 */
	public static Date getTomorrowZeroDate(){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(getTomorrowDay());
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);

		return calendar.getTime();
	}
	
	/**
	 * 获取几分钟后的时间点
	 * @param args
	 * @return 
	 */
	public static Date plusMinute(Calendar c,int args) {
		c.add(Calendar.MINUTE, args);
		return c.getTime();
	}

	/**
	 * 获取当前天时间戳
	 * @return
	 */
	public static final Long format(){
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN.YYYY_MM_DD);
			return sdf.parse(sdf.format(new Date())).getTime();
		} catch (Exception e) {
		}
		return null;
	}
    
    public static void main(String[] args) throws InterruptedException {
		System.out.println(format());
		Thread.sleep(3000);
		System.out.println(format());
//		format(now.getTime(), format);
//		System.out.println(getBetweenDate("2018-11-27","2018-12-02").toString().replace("[","").replace("]", "").replace(" ", ""));
//
//    	System.out.println(format(addDate(getTomorrowZeroDate(), Calendar.MONTH, -3) ,DATE_PATTERN.YYYY_MM_DD_HH_MM_SS));
	}

}
